﻿using Restaurant.Common;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using DapperExtensions;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Reflection;
using Restaurant.Model;
using System.Linq;

namespace Restaurant.Dao
{
    public class BaseServiceDao<T> where T : BaseModel
    {

        //public const string DBSqlStr = ";User Id=sa;Password=12345@sas;";
        public const string DBSqlStr = ";User Id=sa;Password=sa123;";

        /// <summary>
        /// 数据库链接
        /// </summary>
        public static IDbConnection dbConnection = null;

        /// <summary>
        /// 默认排序
        /// </summary>
        public IList<ISort> Sort;


        public BaseServiceDao()
        {
            try
            {
                Sort = new List<ISort>();
                Sort.Add(new Sort { PropertyName = "Id", Ascending = true });

                if (dbConnection == null)
                {
                    string configConnStr = ConfigurationManager.AppSettings["SqlConnectionStr"].ToString();
                    dbConnection = new SqlConnection(configConnStr + DBSqlStr);
                    if (dbConnection.State == ConnectionState.Closed)
                    {
                        dbConnection.Open();
                    }
                }
            }
            catch (Exception ex)
            {
                Log<BaseServiceDao<T>>.Error(ex, ex.Message);
                throw new NullReferenceException("链接异常");
            }
        }


        /// <summary>
        /// 获取单个实体
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public virtual async Task<T> GetModelAsync(long Id)
        {
            try
            {
                var data = await dbConnection.GetAsync<T>(Id);
                return data;
            }
            catch (Exception ex)
            {
                Log<BaseServiceDao<T>>.Error(ex, ex.Message);
                return null;
            }
        }


        /// <summary>
        /// 查询列表
        /// </summary>
        /// <param name="where">条件</param>
        /// <param name="sorts">排序</param>
        /// <param name="isPager">是否使用分页</param>
        /// <param name="pageSize">页码</param>
        /// <param name="pageCount">页数</param>
        /// <returns></returns>
        public virtual async Task<Tuple<IEnumerable<T>, int>> GetListAsync(IPredicateGroup where, IList<ISort> sorts = null, bool isPager = false, int pageSize = 0, int pageCount = 10)
        {
            Tuple<IEnumerable<T>, int> result = null;
            try
            {
                if (null != sorts)
                    Sort = sorts;

                IList<IPredicate> predList = new List<IPredicate>();

                predList.Add(where);

                predList.Add(Predicates.Field<T>(p => p.RemoveSign, Operator.Eq, 0));

                where = Predicates.Group(GroupOperator.And, predList.ToArray());

                IEnumerable<T> data = null;
                if (isPager)
                {
                    data = await dbConnection.GetPageAsync<T>(where, Sort, pageSize, pageCount);
                }
                else
                {
                    data = await dbConnection.GetListAsync<T>(where, Sort);
                }


                int total = await dbConnection.CountAsync<T>(where);
                result = new Tuple<IEnumerable<T>, int>(data, total);
                return result;
            }
            catch (Exception ex)
            {
                Log<BaseServiceDao<T>>.Error(ex, ex.Message);
                return result;
            }
        }


        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public virtual async Task<T> SaveAsync(T model)
        {
            try
            {
                await dbConnection.InsertAsync(model);
                return model;
            }
            catch (Exception ex)
            {
                Log<BaseServiceDao<T>>.Error(ex, ex.Message);
                return default;
            }
        }

        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public virtual async Task<T1> SaveAsync<T1>(T1 model)where T1: BaseModel
        {
            try
            {
                await dbConnection.InsertAsync( model);
                return model;
            }
            catch (Exception ex)
            {
                Log<BaseServiceDao<T>>.Error(ex, ex.Message);
                return default;
            }
        }



        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="model">对象</param>
        /// <returns></returns>
        public virtual async Task<T> ModifyAsync(T model)
        {
            try
            { 
                Type fModel = typeof(T);
                //修改事件
                PropertyInfo property = fModel.GetProperty("ModificationTime");
                if (property != null)
                    fModel.GetProperty("ModificationTime").SetValue(model, Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));

                await dbConnection.UpdateAsync(model);
                return model;
            }
            catch (Exception ex)
            {
                Log<BaseServiceDao<T>>.Error(ex, ex.Message);
                return default;
            }
        }


        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="model">对象</param>
        /// <returns></returns>
        public virtual async Task<bool> RemoveAsync(long id )
        {
            try
            { 
                var model = await GetModelAsync(id);

                Type fModel = typeof(T);

                //删除
                PropertyInfo property = fModel.GetProperty("RemoveSign");
                if (property != null)
                    fModel.GetProperty("RemoveSign").SetValue(model, 1);

                //修改时间
                property = fModel.GetProperty("ModificationTime");
                if (property != null)
                    fModel.GetProperty("ModificationTime").SetValue(model, Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));

                bool data = await dbConnection.UpdateAsync(model);
                return data;
            }
            catch (Exception ex)
            {
                Log<BaseServiceDao<T>>.Error(ex, ex.Message);
                return false;
            }
        }
    }
}
